#include "ByteReader.h"

//
// constructors
//
ByteReader::ByteReader(void)
{
	InitVars();
}

ByteReader::ByteReader( void* pBuff, DWORD dwSize )
{
	Assign( pBuff, dwSize );
}

//
// destructor
//
ByteReader::~ByteReader(void)
{
}

//
// Purpose:
//   Member variable initializer
//
void ByteReader::InitVars()
{
	pBuffer       = NULL;
	cbBuffer      = 0;
	dwBitsLeft    = dwBitsTotal = 0;
	byBits2Do     = 8;
	byCur         = 0;
	dwIndex       = 0;

	return;
}

//
// Purpose:
//   Class initialization handler
//
BOOL ByteReader::Assign( void *pBuff, DWORD dwSize )
{
	InitVars();
	if ( !pBuff || !dwSize)
		return FALSE; // ERR

	this->pBuffer  = pBuff;
	this->cbBuffer = dwSize;

	dwBitsLeft     = dwBitsTotal = dwSize * 8;
	byCur          = ((PBYTE)pBuff)[ dwIndex++ ];

	return TRUE; // OK
}

DWORD ByteReader::GetUnusedBitCount()
{
	return dwBitsLeft;
}

DWORD ByteReader::GetTotalBitCount()
{
	return dwBitsTotal;
}

//
// Purpose:
//   Returns the number of accessed bytes
//
DWORD ByteReader::GetReadByteCount()
{
	DWORD  dwcBitsRead  = (dwBitsTotal - dwBitsLeft);
	DWORD  c = (DWORD)(dwcBitsRead / 8);

	if ( dwcBitsRead % 8 ) // round up !
		++c;

	return c;
}

//
// Purpose:
//   The key member function for the buffer querying
//
BYTE ByteReader::ReadBit()
{
	BYTE bit = 0;

	if ( dwBitsLeft == 0 )
		return -1; // ERR

	bit = byCur & 1;
	byCur >>= 1;
	--dwBitsLeft;
	--byBits2Do;

	// did we already build a complete byte ? -> paste in buffer
	if ( !byBits2Do )
	{
		byCur = ((PBYTE)pBuffer)[ dwIndex++ ];
		byBits2Do = 8;
	}

	return bit; // OK
}

//
// Purpose:
//   Read a 1 byte variable from the buffer
//
BYTE ByteReader::ReadByte()
{
	BYTE byte = 0;

	for ( UINT i = 0; i < 8; i++ )
	{
		byte  |= (ReadBit() << 7);
		if ( i != 7) // don't shift to last byte !
            byte >>= 1;
	}
	return byte; // OK
}

//
// Purpose:
//   Read a 2 byte variable from the buffer
//
WORD ByteReader::ReadWord()
{
	WORD word = 0;

	for ( UINT i = 0; i < 16; i++ )
	{
		word  |= (ReadBit() << 15);
		if ( i != 15) // don't shift to last byte !
            word >>= 1;
	}
	return word; // OK
}

//
// Purpose:
//   Read a 4 byte variable from the buffer
//
DWORD ByteReader::ReadDword()
{
	DWORD dword = 0;

	for ( UINT i = 0; i < 32; i++ )
	{
		dword  |= (ReadBit() << 31);
		if ( i != 31) // don't shift to last byte !
            dword >>= 1;
	}
	return dword; // OK
}

//
// Purpose:
//   Read a user defined number of bits from the buffer
//
DWORD ByteReader::ReadBits( DWORD dwBitCount )
{
	DWORD dword = 0;

	if ( dwBitCount > 32 )
		return -1; // ERR

	for ( UINT i = 0; i < 32; i++ )
	{
		if ( i < dwBitCount )
			dword |= (ReadBit() << 31);
		if ( i != 31) // don't shift to last byte !
			dword >>= 1;
	}

	return dword; // OK
}